﻿using Newtonsoft.Json;
using RestSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;

namespace DailyReport.Helpers
{
    internal class BosonApi
    {
        public string Key { get; set; }
        public int RemainReview { get; set; }
        public int RemainKeywords { get; set; }
        public int RemainTag { get; set; }
        public int RemainCalssify { get; set; }
        public int RemainDepparser { get; set; }
        public int RemainTime { get; set; }
        public int RemainSummary { get; set; }
        public int RemainNer { get; set; }
        public int RemainCluster { get; set; }
        public int RemainComments { get; set; }
        public int RemainSuggest { get; set; }
        public int RemainSentiment { get; set; }
    }

	public class DrBosonHelper
	{
        private const int MaxCountLimitOneReq = 100;    //单次调用API数组长度限制
        private const string UrlSentiment = "http://api.bosonnlp.com/sentiment/analysis";

        private static List<BosonApi> listApi;          //可用的API信息列表

        static DrBosonHelper()
        {
            //建立可调用API列表
            listApi = new List<BosonApi>();
            string[] apis = { "Hg_PRFF4.18005.HBsGWEEL5IMO", "Z3Y1JRpO.9721.fvJuTAl3IA0a",
                "eU9PnoEt.18010.WwrlFI2WuB9g", "CLbdOvYv.18011.LSMsssB89Rdk" };
            foreach (string api in apis)
            {
                listApi.Add(new BosonApi
                {
                    Key = api,
                    RemainReview = 500,
                    RemainKeywords = 500,
                    RemainTag = 500000,
                    RemainCalssify = 500,
                    RemainDepparser = 500,
                    RemainTime = 500,
                    RemainSummary = 500,
                    RemainNer = 500,
                    RemainCluster = 500,
                    RemainComments = 500,
                    RemainSuggest = 500,
                    RemainSentiment = 500
                });
            }
        }

        /// <summary>
        /// 分割数组
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="data">待分割数组</param>
        /// <param name="size">分割长度</param>
        /// <returns></returns>
        private static List<T[]> SplitArray<T>(T[] data, int size)
        {
            List<T[]> list = new List<T[]>();
            for (int i = 0; i < data.Length / size; i++)
            {
                T[] r = new T[size];
                Array.Copy(data, i * size, r, 0, size);
                list.Add(r);
            }
            if (data.Length % size != 0)
            {
                T[] r = new T[data.Length % size];
                Array.Copy(data, data.Length - data.Length % size, r, 0, data.Length % size);
                list.Add(r);
            }
            return list;
        }

        private static string GetRouteGroup(string url)
        {
            string str = url.ToLower().Replace("http://", "").Replace("https://", "").Replace("api.bosonnlp.com/", "");
            var strs = str.Split('/');
            return strs[0];
        }

        private static string GetApi(string url, int countUse)
        {
            var strPort = GetRouteGroup(url);
            if (strPort.Contains("sentiment"))
            {
                if (!listApi.Any(a => a.RemainSentiment > countUse)) return null;
                return listApi.First(a => a.RemainSentiment > countUse).Key;
            }

            return null;
        }

        private static void FixApiRemaining(string url, string api, IRestResponse response)
        {
            int remaining = -1;
            foreach (var item in response.Headers)
            {
                if (item.Name == "X-Count-Limit-Remaining")
                {
                    remaining = int.Parse(item.Value.ToString());
                    break;
                }
            }
            if (remaining == -1) return;

            var strPort = GetRouteGroup(url);
            if (strPort.Contains("sentiment"))
            {
                var bosonApi = listApi.First(a => a.Key == api);
                bosonApi.RemainSentiment = remaining;
            }
        }

        /// <summary>
        /// 得到响应
        /// </summary>
        /// <param name="url">请求地址</param>
        /// <param name="text">请求body文本</param>
        /// <param name="method">请求调用的Http方法</param>
        /// <param name="countUse">请求消耗的限制长度</param>
        /// <returns></returns>
        public static IRestResponse GetRestResponse(string url, string text, Method method = Method.POST, int countUse = 1)
        {
            if (string.IsNullOrEmpty(url) || string.IsNullOrEmpty(text)) return null;
            var api = GetApi(url, countUse);
            if (api == null) return null;

            var client = new RestClient(url);
            var request = new RestRequest(method);
            request.AddHeader("content-type", "application/json");
            request.AddHeader("x-token", api);
            request.AddHeader("accept", "application/json");
            request.AddParameter("application/json", text, ParameterType.RequestBody);
            IRestResponse response = client.Execute(request);

            FixApiRemaining(url, api, response);
            return response;
        }

        public static double NlpSentiment(string text)
        {
            string bodySend = "[" + text + "]";
            IRestResponse response = GetRestResponse(UrlSentiment, bodySend, Method.POST);

            var res = JsonConvert.DeserializeObject<List<List<double>>>(response.Content);
            return res[0][0];
        }

        public static IEnumerable<double> NlpSentiment(IEnumerable<string> texts)
        {
            //待分析数组长度
            int count = texts.Count();
            //待分析数组超出单次调用范围
            if (count > MaxCountLimitOneReq)
            {
                List<double> listVal = new List<double>();
                var listText = SplitArray<string>(texts.ToArray(), MaxCountLimitOneReq);
                foreach (var list in listText)
                {
                    listVal.AddRange(NlpSentiment(list));
                }
                return listVal;
            }
            //待分析数组在单次调用范围内
            StringBuilder sb = new StringBuilder("[");
            foreach (var text in texts)
            {
                sb.Append("\"" + text + "\",");
            }
            string bodySend = sb.ToString().TrimEnd(',') + "]";

            IRestResponse response = GetRestResponse(UrlSentiment, bodySend, Method.POST, count);

            var res = JsonConvert.DeserializeObject<List<List<double>>>(response.Content);

            
            double[] vals = new double[count];
            for (int i = 0; i < count; i++)
            {
                vals[i] = res[i][0];
            }
            return vals;
        }

    }
}